﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using ServiceStack.Redis;
using ServiceStack.Text;
using ServiceStack.Redis.Generic;

using Newtonsoft.Json;

namespace Game
{
    class RemotePlayer
    {
        RedisClient _redis;
        UI _ui;

        delegate void  FuntionActor(JsonObject jObj);
        public List<Dictionary<string, int>> AILog;
        private string DoneKey { get; set; }
        private string MapKey { get; set; }
        private string SlimesKey { get; set; }
        private string FunKey { get; set; }
        private string AILogKey { get; set; }

        private static string YesValue = "yes";
        private static string NoValue = "no";

        private Dictionary<string, FuntionActor> _actors;

        public RemotePlayer(UI ui, string redisId, string clientPath = "localhost") {
            _redis = new RedisClient(clientPath);
            _ui = ui;
            DoneKey = "done:" + redisId;
            MapKey = "map:" + redisId;
            SlimesKey = "slimes:" + redisId;
            FunKey = "function:" + redisId;
            AILogKey = "ailog:" + redisId;

            AILog = null;
        }

        public bool Run() {
            _redis.SetEntry(DoneKey, NoValue);
            _redis.SetEntryInHash(MapKey, "width", _ui.Map.Width.ToString());

            UpdateAILog();
            UpdateSlimeInfo();

            while (_redis.GetValue(DoneKey) != YesValue) {
                procFuntions();
                UpdateSlimeInfo();
                System.Threading.Thread.Sleep(80);
            }

            return true;
        }

        private void UpdateSlimeInfo() {
            string mySlimes = JsonConvert.SerializeObject(_ui.GetPlayer(0).Slimes, Formatting.Indented);
            _redis.SetEntryInHash(SlimesKey, "my", mySlimes);
            string enemySlimes = JsonConvert.SerializeObject(_ui.GetPlayer(1).Slimes, Formatting.Indented);
            _redis.SetEntryInHash(SlimesKey, "enemy", enemySlimes);
        }

        private void UpdateAILog() {
            if (AILog == null) { return; }
            string log = JsonConvert.SerializeObject(AILog, Formatting.Indented);
            Console.WriteLine("log: " + AILogKey + " = " + log);
            _redis.SetEntry(AILogKey, log);
        }

        private void procFuntions() {
            var orderJson = _redis.GetValue(FunKey);
            if (orderJson != null) {
                var jObj = JsonObject.Parse(orderJson);
                string f = (string)jObj["function"];
                if (f == "move") {
                    int id = Int32.Parse(jObj["id"]);
                    int x = Int32.Parse(jObj["x"]);
                    int y = Int32.Parse(jObj["y"]);
                    Console.WriteLine("Move id: "+ id.ToString()+", x:"+x.ToString()+", y:"+y.ToString());
                    _ui.Move(id, new Position(x,y), 'a');
                } else if (f == "attack") {
                    int attackerId = Int32.Parse(jObj["attacker_id"]);
                    int targetId = Int32.Parse(jObj["target_id"]);
                    Slime attacker = null;
                    Slime target = null;

                    Console.WriteLine("Atk attackerId: " + attackerId.ToString() + ", targetId:" + targetId.ToString());

                    foreach (var slime in _ui.GetPlayer(0).Slimes) {
                        if (slime.ID == attackerId) {
                            attacker = slime;
                            break;
                        }
                    }
                    foreach (var slime in _ui.GetPlayer(1).Slimes) {
                        if (slime.ID == targetId) {
                            target = slime;
                            break;
                        }
                    }
                    _ui.Atk(attacker, target);
                } else if (f == "bear") {
                    string typeStr = jObj["type"];
                    int x = Int32.Parse(jObj["x"]);
                    int y = Int32.Parse(jObj["y"]);
                    SlimesCategory type = SlimesCategory.ARCHER;
                    if (typeStr == "knight") {
                        type = SlimesCategory.KNIGHT;
                    } else if (typeStr == "pawn") {
                        type = SlimesCategory.PAWN;
                    }
                    Console.WriteLine("Bron x:" + x.ToString() + "  y:" + y.ToString());
                    _ui.Born(type, new Position(x, y));
                } else if (f == "kill") {
                    int id = Int32.Parse(jObj["id"]);
                    char side = jObj["Side"][0];
                    _ui.Kill(id, side);
                }

            }
            _redis.RemoveEntry(FunKey);
        }

    }
}
